package com.prism.cluster;

import java.util.ArrayList;
import java.util.Random;
import com.prism.moodme.data.Data;

public class ClusterSet {

	private int kay;

	private ArrayList<Cluster> clusters;

	public ClusterSet(int kay, ArrayList<Data> data){
		setKay(kay);
		setClusters(new ArrayList<Cluster>());
		init(data);
	}

	public ClusterSet(ClusterSet clusterset){
		setKay(clusterset.getKay());
		setClusters(new ArrayList<Cluster>());
		next(clusterset.getClusters());
	}

	private void next(ArrayList<Cluster> prev){
		ArrayList<Data> cents = new ArrayList<Data>();
		ArrayList<Data> data = new ArrayList<Data>();
		for(Cluster curr : prev){
			cents.add(curr.getCentroid());
			data.addAll(curr.getMembers());
		}

		ArrayList<ArrayList<Data>> clusters = new ArrayList<ArrayList<Data>>();
		for(int i=0; i<cents.size(); i++){
			ArrayList<Data> _curr = new ArrayList<Data>();
//			_curr.add(curr);
			clusters.add(_curr);
		}

		for(Data member : data){
			if(cents.contains(data))
				continue;
			int minCent = 0;
			double minDist = member.euclid(cents.get(0));

			for(int i=0; i<cents.size(); i++){
				Data centroid = cents.get(i);
				double dist = member.euclid(centroid);
				if (dist < minDist){
					minCent = i;
					minDist = dist;
				}
			}
			clusters.get(minCent).add(member);
		}
		for(int i=0; i<clusters.size(); i++)
			getClusters().add(new Cluster(clusters.get(i)));

	}

	private void init(ArrayList<Data> data){

		ArrayList<Integer> index = getRandom(data);
		ArrayList<Data> cents = new ArrayList<Data>();
		for(int i : index)
			cents.add(data.get(i));

		ArrayList<ArrayList<Data>> clusters = new ArrayList<ArrayList<Data>>();
		for(int i=0; i<cents.size(); i++){
			ArrayList<Data> _curr = new ArrayList<Data>();
//			_curr.add(curr);
			clusters.add(_curr);
		}

		for(Data member : data){
			if(cents.contains(data))
				continue;
			int minCent = 0;
			double minDist = member.euclid(cents.get(0));

			for(int i=0; i<cents.size(); i++){
				Data centroid = cents.get(i);
				double dist = member.euclid(centroid);
				if (dist < minDist){
					minCent = i;
					minDist = dist;
				}
			}
			clusters.get(minCent).add(member);
		}
		for(int i=0; i<clusters.size(); i++)
			getClusters().add(new Cluster(clusters.get(i)));
	}

	private ArrayList<Integer> getRandom(ArrayList<Data> data){
		ArrayList<Integer> rand = new ArrayList<Integer>();
		Random random = new Random(System.currentTimeMillis());
		for(int i=0; i<getKay(); i++){
			int val = random.nextInt(data.size());
			while(rand.contains(val))
				val = random.nextInt(getKay());
			rand.add(val);
		}
		return rand;
	}


	public void setClusters(ArrayList<Cluster> clusters) {
		this.clusters = clusters;
	}

	/**
	 *
	 * @return
	 */
	public ArrayList<Cluster> getClusters() {
		return clusters;
	}

	private void setKay(int kay){
		this.kay = kay;
	}

	public int getKay(){
		return this.kay;
	}

	public boolean equals(ClusterSet other){
		if(getKay() != other.getKay())
			return false;
		for(Cluster clust : getClusters()){
			boolean match = false;
			for(Cluster otherclust : other.getClusters()){
				if(clust.equals(otherclust)){
					match = true;
					break;
				}

			}
			if(!match)
				return false;
		}
		return true;
	}

}
